#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <pthread.h>
#include <errno.h>
void *ClientPthread_Handler(void *data)
{
    pthread_detach(pthread_self());//线程分离，在子线程中独自做资源回收处理
    char recive_buff[1024];
    int ret = 0;
    int new_client_fd = *(int *)data; //先把数据强制转换为 int*的指针，再用 *取指针里的内容
    while (1)
    {
        /* code */
        memset(recive_buff,0,sizeof(recive_buff)); //清空缓冲区
        ret = recv(new_client_fd, recive_buff, 1024, 0);
        if (ret == 0) //客户端断开连接
        {
            /* code */
            printf("%d client unconnect\n", new_client_fd);
            break; //跳出
        }
        else if (ret == -1)
        {
            printf("recv return -1. error = %d\n",errno);
            if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN)
            {
                continue;
            }
            else
            {
                break;
            }
        }
        else
        {
            printf("reacive data \n");
            printf("%s\n", recive_buff);
        }
    }
    close(new_client_fd);
    pthread_exit(0);
}
int main(int argc, char const *argv[])
{
    /* code */
    int socket_ret = 0;
    int pthread_ret = 0;
    int value = 1;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    socklen_t clientAddr_len = 0;
    pthread_t client_pthread;
    /* 创建socket套接字 */
    int socket_fd = socket(AF_INET, SOCK_STREAM, 0); // IPV4 TCP 连接
    if (socket_fd == -1)
    {
        perror("socket\n");
        exit(-1);
    }
    socket_ret = setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,(const char*)&value,sizeof(int));//配置端口重用
    if (socket_ret ==-1)
    {
        /* code */
        perror("setsocketopt\n");
    }
    
    /* bind绑定套接字 */
    memset(&server_addr, 0, sizeof(struct sockaddr)); //清空结构体
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(1235);              //设置本地端口，并转化为网络字节序 端口号用 htons 16位的来转换
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //默认获取本地网卡IP
    socket_ret = bind(socket_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr_in));
    if (socket_ret == -1)
    {
        perror("bind\n");
        close(socket_fd); //关闭socket 套接字 描述符
        exit(-1);
    }
    /* 建立linsten监听 */
    socket_ret = listen(socket_fd, 10);
    if (socket_ret == -1)
    {
        perror("listen\n");
        close(socket_fd); //关闭socket 套接字 描述符
        exit(-1);
    }
    while (1)
    {
        /* code */
        /* 等待连接 */
        printf("wait connect .......\n");
        memset(&client_addr, 0, sizeof(struct sockaddr_in));
        int client_fd = accept(socket_fd, (struct sockaddr *)&client_addr, &clientAddr_len); //等待客户端连接
        if (client_fd == -1)
        {
            perror("accept\n");
            close(socket_fd); //关闭socket 套接字 描述符
            close(client_fd); //关闭socket 套接字 描述符
            exit(-1);
        }
        printf("client connect success\n");
        printf("有新的客户端接入，创建 新的线程来处理数据\n");
        pthread_ret = pthread_create(&client_pthread, NULL, ClientPthread_Handler, (void *)&client_fd);
        if (pthread_ret == -1)
        {
            /* code */
            printf("pthread create failed\n");
        }
    }
    return 0;
}
